package com.winit.openapi.wop.inbound.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.druid.util.Base64;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.winit.common.query.Page;
import com.winit.common.spi.context.CommandContext;
import com.winit.common.utils.Collections3;
import com.winit.erp.spi.bpartner.vo.Bpartner;
import com.winit.oms.spi.common.vo.PageVo;
import com.winit.oms.spi.inbound.InboundCustomsDataFileService;
import com.winit.oms.spi.inbound.InboundOrderFeeService;
import com.winit.oms.spi.inbound.InboundOrderService;
import com.winit.oms.spi.inbound.InboundPackageService;
import com.winit.oms.spi.inbound.WHInboundOrderService;
import com.winit.oms.spi.inbound.command.BatchAddInboundCustomsDataFileCommand;
import com.winit.oms.spi.inbound.command.CreateInboundOrderCommand;
import com.winit.oms.spi.inbound.command.OperateByKeyCommand;
import com.winit.oms.spi.inbound.command.PrintInboundPackageLabelCommand;
import com.winit.oms.spi.inbound.command.QueryInboundPackinglistCommand;
import com.winit.oms.spi.inbound.command.SearchInboundOrderCommand;
import com.winit.oms.spi.inbound.command.WHQueryInboundOrderListCommand;
import com.winit.oms.spi.inbound.vo.InboundCustomsDataFileVo;
import com.winit.oms.spi.inbound.vo.InboundEnumConstant;
import com.winit.oms.spi.inbound.vo.InboundOrderFeeResultVo;
import com.winit.oms.spi.inbound.vo.InboundOrderFeeVo;
import com.winit.oms.spi.inbound.vo.InboundOrderVo;
import com.winit.oms.spi.inbound.vo.InboundPackinglistVo;
import com.winit.openapi.constants.ApiConstant;
import com.winit.openapi.constants.EnumConstant;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.controller.BaseController;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.util.DateUtil;
import com.winit.openapi.util.PDFBox4MergePDF;
import com.winit.openapi.util.ValidateUtil;
import com.winit.openapi.wop.inbound.builder.InboundOrderBuilder;
import com.winit.openapi.wop.inbound.constant.WHInboundConstant;
import com.winit.openapi.wop.inbound.constant.InboundParameter.InputInboundCreate;
import com.winit.openapi.wop.inbound.validator.InboundOrderfieldValidator;
import com.winit.pms.spi.winit.WinitProductItemService;
import com.winit.pms.spi.winit.WinitProductService;
import com.winit.pms.spi.winit.command.WinitProductQueryCommand;
import com.winit.pms.spi.winit.vo.WinitProduct;
import com.winit.tms.spi.common.TMSConstants;
import com.winit.ups.spi.command.CodeCommand;
import com.winit.ups.spi.warehouse.WarehouseService;
import com.winit.ups.spi.warehouse.vo.WarehouseVo;

/**
 * 入库单对外API服务接口类
 * 
 * @version <pre>
 * Author   Version     Date        Changes
 * minghao.deng     1.0         2016年9月20日  Created
 *
 * </pre>
 * @since 1.
 */
@Controller
@RequestMapping(value = "winit/wh/inbound")
public class WHInboundOrderController extends BaseController {
	
    private static Logger          logger = LoggerFactory.getLogger(WHInboundOrderController.class);
    private final static String[] SUPPORT_FILE_TYPE = {"jpg", "gif", "png", "jpeg", "pdf", "doc", "docx", "xls", "csv", "xlsx"};
    @Resource
    private WHInboundOrderService  whInboundOrderService;
    @Resource
    private InboundOrderService    inboundOrderService;
    @Resource
    private InboundPackageService  inboundPackageService;
    @Resource
    private WinitProductService    productService;
    @Resource
    private InboundOrderFeeService inboundOrderFeeService;
    @Resource
    private WarehouseService       upsWarehouseService;
    @Resource
    private WinitProductService    winitProductService;
    @Resource
    private WinitProductItemService winitProductItemService;
    @Resource
    private InboundCustomsDataFileService inboundCustomsDataFileService;

    /**
     * 查询入库单详情接口
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/getOrderDetail")
    public String getOrderDetail(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object obj = requestMsg.getData();
        JSONObject json = null;
        if (obj instanceof JSONObject) {
            json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, "orderNo");
            ValidateUtil.validMaxLength(json, "orderNo", 50, true);
            ValidateUtil.validMaxLength(json, "isIncludePackage", 10, false);

        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }
        String isIncludePackage = json.getString("isIncludePackage");
        boolean isPackageInclude = "Y".equals(isIncludePackage);
        SearchInboundOrderCommand command = new SearchInboundOrderCommand();
        command.setOrderNo(json.getString("orderNo"));
        InboundOrderVo vo = whInboundOrderService.queryOrderDetailForAPI(command);
        if (null == vo) {
            throw new ApiException(ErrorCode.ORDER_NO_NOT_EXSIT, "orderNo");
        }
        Map<String, Object> data = InboundOrderBuilder.buildReturnInboundOrderInfoForAPI(vo, isPackageInclude);
        responseMsg.setData(data);

        return SUCCESS;

    }

    /**
     * 查询入库单列列表接口
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/getOrderList")
    public String getOrderList(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object obj = requestMsg.getData();
        JSONObject json = null;
        if (obj instanceof JSONObject) {
            json = (JSONObject) obj;

            ValidateUtil.validMaxLength(json, "orderType", 50, false);
            ValidateUtil.validMaxLength(json, "destinationWarehouseCode", 50, false);
            ValidateUtil.validMaxLength(json, "inspectionWareHouseCode", 50, false);
            ValidateUtil.validMaxLength(json, "orderCreateDateEnd", 50, false);
            ValidateUtil.validMaxLength(json, "orderCreateDateStart", 50, false);
            ValidateUtil.validMaxLength(json, "winitProductCode", 50, false);

            if (json.containsKey("winitProductCode")) {
                String winitProductCode = json.getString("winitProductCode");
                WinitProductQueryCommand command = new WinitProductQueryCommand();
                command.setCode(winitProductCode);
                WinitProduct product = productService.queryProduct(command);
                if (null == product) {
                    throw new ApiException(ErrorCode.WINIT_PRODUCT_NOT_EXISTS, winitProductCode);
                }
            }

            if (json.containsKey("orderCreateDateStart") && json.containsKey("orderCreateDateEnd")) {
                ValidateUtil.validDateString(json, "orderCreateDateStart", "yyyy-MM-dd");
                ValidateUtil.validDateString(json, "orderCreateDateEnd", "yyyy-MM-dd");
                ValidateUtil.validDateBefore(json, "orderCreateDateStart", "orderCreateDateEnd");
            } else if (json.containsKey("orderCreateDateStart") || json.containsKey("orderCreateDateEnd")) {

                throw new ApiException(ErrorCode.FIELD_NOT_NULL,
                    json.containsKey("orderCreateDateStart") ? "orderCreateDateEnd" : "orderCreateDateStart");
            }

        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }
        if (json.containsKey("orderType")) {
            // 订单类型校验
            if (!WHInboundConstant.InboundOrderType.isValidOrderType(json.getString("orderType"))) {
                throw new ApiException(ErrorCode.FEILD_NOT_MATCH, "orderType");
            }
        }
        WHQueryInboundOrderListCommand command = new WHQueryInboundOrderListCommand();
        //修复没有传客户编码的BUG
        Bpartner  bpartner = CommandContext.getContext().get(ApiConstant.API_BPARTNER);
        command.setCustomerCode(bpartner.getValue());

        if (json.containsKey("orderType")) {
            command.setEntryWhType(json.getString("orderType"));
        }
        if (json.containsKey("destinationWarehouseCode")) {
            checkWarehouse(json.getString("destinationWarehouseCode"));
            command.setDestWhCode(json.getString("destinationWarehouseCode"));
        }
        if (json.containsKey("inspectionWarehouseCode")) {
            checkWarehouse(json.getString("inspectionWarehouseCode"));
            command.setInspectionWhCode(json.getString("inspectionWarehouseCode"));
        }
        if (json.containsKey("orderCreateDateEnd")) {
//            Date toDate = DateUtil.parse2Date(json.getString("orderCreateDateEnd"), DateUtil.SIMPLE_DATE_STRING);
//            command.setDateTo(toDate);
            
            String orderCreateDateEndObj = json.getString("orderCreateDateEnd");
            if(StringUtils.isNotBlank(orderCreateDateEndObj)){
                String toDate = DateUtil.parse2String(json.getDate("orderCreateDateEnd"), DateUtil.FULL_DATE_STRING2);
                command.setDateTo(DateUtil.parse2Date(toDate, DateUtil.FULL_DATE_STRING));
            }
        }
        if (json.containsKey("orderCreateDateStart")) {
//          Date fromDate = DateUtil.parse2Date(json.getString("orderCreateDateStart"), DateUtil.SIMPLE_DATE_STRING);
//          command.setDateFrom(fromDate);
            String orderCreateDateStartObj = json.getString("orderCreateDateStart");
            if(StringUtils.isNotBlank(orderCreateDateStartObj.toString())){
                String startDate = DateUtil.parse2String(json.getDate("orderCreateDateStart"), DateUtil.FULL_DATE_STRING2);
                command.setDateFrom(DateUtil.parse2Date(startDate, DateUtil.FULL_DATE_STRING2));
            }
        }
        if (json.containsKey("winitProductCode")) {
            command.setWinitProductCode(json.getString("winitProductCode"));
        }
        if (json.containsKey("pageParams")) {
            ValidateUtil.validNotNull(json.getJSONObject("pageParams"), "pageSize");
            ValidateUtil.validNotNull(json.getJSONObject("pageParams"), "pageNo");
            ValidateUtil.validInteger(json.getJSONObject("pageParams"), "pageSize", true);
            ValidateUtil.validInteger(json.getJSONObject("pageParams"), "pageNo", true);

          //  PageVo pageVo = setPageParams(json.get("pageParams"));
            command.setPageVo(buildPageVo(json.getJSONObject("pageParams")));
        }

        Page<InboundOrderVo> orderListPage = whInboundOrderService.queryOrderList(command);
        List<InboundOrderVo> content = orderListPage.getContent();
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> data = new HashMap<String, Object>();
        for (InboundOrderVo inboundOrderVo : content) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("orderNo", inboundOrderVo.getOrderNo());
            map.put("status", inboundOrderVo.getStatus());
            map.put("weight", inboundOrderVo.getOrderWeight() + "|" + inboundOrderVo.getActualOrderWeight());
            map.put("volume", inboundOrderVo.getOrderVolume() + "|" + inboundOrderVo.getActualOrderVolume());
            map.put("totalPackageQty", inboundOrderVo.getActualOrderPackageQty());
            map.put("totalItemQty", inboundOrderVo.getActualOrderItemQty());
            map.put("orderCreateDate", inboundOrderVo.getOrderDate());
            list.add(map);

        }
        data.put("orderList", list);
        Map<String, Object> page = new HashMap<String, Object>();
        page.put("pageNo", orderListPage.getPageable().getPageNumber());
        page.put("pageSize", orderListPage.getPageable().getPageSize());
        page.put("totalCount", orderListPage.total);
        data.put("pageParams", page);

        responseMsg.setData(data);

        return SUCCESS;

    }

    private void checkWarehouse(String warehouseCode) {
        CodeCommand warehouseCommand = new CodeCommand();
        warehouseCommand.setCode(warehouseCode);
        WarehouseVo warehouse = upsWarehouseService.queryWarehouseByCode(warehouseCommand);
        if (null == warehouse) {
            throw new ApiException(ErrorCode.WAREHOUSE_CODE_NOT_EXISTS, warehouseCode);
        }
    }

    /**
     * 打印包裹装箱单标(支持批量打印)
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/printPackageLabel")
    public String printPackageLabel(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        PrintInboundPackageLabelCommand command = new PrintInboundPackageLabelCommand();
        Object obj = requestMsg.getData();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;

            ValidateUtil.validNotNull(json, "orderNo");
            ValidateUtil.validNotNull(json, "labelSize");
            ValidateUtil.validMaxLength(json, "orderNo", 100, true);
            ValidateUtil.validMaxLength(json, "labelSize", 50, true);

            if (json.containsKey("packageNoList")) {
                ValidateUtil.validNotNull(json, "orderNo", "orderNo");
                List<String> sernoList = new ArrayList<String>();

                QueryInboundPackinglistCommand queryPackageListCommand = new QueryInboundPackinglistCommand();
                queryPackageListCommand.setOrderNo(json.getString("orderNo"));
                queryPackageListCommand.setCtx(CommandContext.getContext());
                List<InboundPackinglistVo> packageList = inboundPackageService.queryPackingListByOrderNo(queryPackageListCommand);

                for (Object object : json.getJSONArray("packageNoList")) {
                    JSONObject packageJson = (JSONObject) object;
                    if (!StringUtils.isBlank(packageJson.getString("packageNo"))) {
                        ValidateUtil.validNotNull(packageJson, "packageNo");
                        ValidateUtil.validMaxLength(packageJson, "packageNo", 50, true);
                        sernoList.add(packageJson.getString("packageNo"));
                    } else {
                        ValidateUtil.validNotNull(packageJson, "sellerCaseNo", "sellerCaseNo");
                        ValidateUtil.validMaxLength(packageJson, "sellerCaseNo", 50, false);
                        sernoList.add(this.getPackageSernoBySellerCaseNo(packageJson.getString("sellerCaseNo"),
                            packageList));
                    }
                }
                String printSize = json.getString("labelSize");
                if (StringUtils.isEmpty(printSize)) {
                    printSize = "10x10";
                }
                command.setOrderNo(json.getString("orderNo"));
                command.setPackageSernoList(sernoList);
                command.setPrintSize(printSize);
            } else {
                throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "packageNoList");
            }
        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }
        command.setCtx(CommandContext.getContext());
        List<String> bytes = null;
        // 50个以内直接调服务，大于50个使用多线程
        if (50 > command.getPackageSernoList().size()) {
            bytes = inboundPackageService.printPackageLabel(command);
        } else {

            bytes = batchPrintPackgeLabel(command);
        }
        PDFBox4MergePDF tool = new PDFBox4MergePDF();
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try {
            List<byte[]> byteList = tool.decryptBASE64(bytes);
            tool.merge(byteList, out);
        } catch (IOException e) {
            throw new ApiException(ErrorCode.SYSTEM_ERROR);
        }
        Map<String, Object> dataMap = new HashMap<String, Object>();
        String mergeByte = tool.base64Encode(out.toByteArray());

        if (mergeByte != null && mergeByte.length() > 0) {
            dataMap.put("label", mergeByte);
        }
        responseMsg.setData(dataMap);
        return SUCCESS;
    }

    private String getPackageSernoBySellerCaseNo(String sellerCaseNo, List<InboundPackinglistVo> packageList) {
        if (CollectionUtils.isEmpty(packageList)) {
            return null;
        }
        for (InboundPackinglistVo packageVo : packageList) {
            if (sellerCaseNo.equals(packageVo.getCaseNo())) {
                return packageVo.getPackageSerNo();
            }
        }
        return sellerCaseNo;
    }

    /**
     * 海外仓入库单费用预估
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/estimateOrderFee")
    public String estimateOrderFee(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object obj = requestMsg.getData();
        OperateByKeyCommand<String> command = new OperateByKeyCommand<String>();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, "orderNo");
            ValidateUtil.validMaxLength(json, "orderNo", 50, true);
            command.setKey(json.getString("orderNo"));

            SearchInboundOrderCommand queryOrderCommand = new SearchInboundOrderCommand();
            queryOrderCommand.setOrderNo(json.getString("orderNo"));
            try {
                whInboundOrderService.queryOrderDetailForAPI(queryOrderCommand);
            } catch (Exception e) {
                throw new ApiException(ErrorCode.ORDER_NO_NOT_EXSIT, json.getString("orderNo"));
            }
        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }

        // 调用费用预估接口
        InboundOrderFeeResultVo result = inboundOrderFeeService.estimateCalculateFee(command);
        List<Map<String, Object>> chargesList = new ArrayList<Map<String, Object>>();
        Map<String, Object> resultMap = new HashMap<String, Object>();
        Map<String, Object> dataMap = new HashMap<String, Object>();
        for (InboundOrderFeeVo fee : result.getFeeList()) {
            dataMap = new HashMap<String, Object>();
            dataMap.put("feeName", fee.getName());
            dataMap.put("feeNode", fee.getNode());
            dataMap.put("fee", fee.getFee().setScale(2, BigDecimal.ROUND_HALF_UP)); // 保留2位小数
            dataMap.put("feeCurrency", fee.getCurrency());
            chargesList.add(dataMap);
        }
        resultMap.put("feeList", chargesList);
        resultMap.put("totalFeeCurrency", result.getTotalFeeCurrency());
        resultMap.put("totalFee", result.getTotalFee().setScale(2, BigDecimal.ROUND_HALF_UP));// 保留2位小数
        responseMsg.setData(resultMap);
        responseMsg.setMsg("SUCCESS");

        return SUCCESS;
    }

    /**
     * 设置分页参数
     * 
     * @param object
     * @return
     */
    public PageVo setPageParams(Object object) {
        if (object == null) return null;
        if (object instanceof JSONObject) {
            JSONObject json = (JSONObject) object;
            if (json.containsKey("pageVo")) {
                Object obj = json.get("pageVo");
                if (obj instanceof JSONObject) {
                    return buildPageVo(obj);
                } else {
                    throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "pageVo");
                }
            }
        } else {
            throw new ApiException(ErrorCode.JSON_FORMAT_ERROR, "data");
        }
        return null;
    }

    private static PageVo buildPageVo(Object obj) {
        PageVo pageVo = new PageVo();
        JSONObject pageParams = (JSONObject) obj;
        ValidateUtil.validInteger(pageParams, "pageNo");
        ValidateUtil.validInteger(pageParams, "pageSize");
        if (pageParams.containsKey("pageNo")) {
            int pageNo = pageParams.getInteger("pageNo");
            if (pageNo < 1) {
                throw new ApiException(ErrorCode.FIELD_ERROR, "pageNo");
            }
            pageVo.setPageNo(pageNo);
        }
        if (pageParams.containsKey("pageSize")) {
            int pageSize = pageParams.getInteger("pageSize");
            if (pageSize < 1) {
                throw new ApiException(ErrorCode.FIELD_ERROR, "pageSize");
            }
            pageVo.setPageSize(pageSize);
        }
        return pageVo;
    }

    private List<String> batchPrintPackgeLabel(PrintInboundPackageLabelCommand command) {
        if (null == command.getPackageSernoList()) {
            return null;
        }
        List<String> result = new ArrayList<String>();
        List<String> packageSernoList = command.getPackageSernoList();
        int unit = 50;
        int total = packageSernoList.size();
        int count = total / unit;
        List<Future<List<String>>> taskList = new ArrayList<Future<List<String>>>();
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < count; i++) {
            PrintInboundPackageLabelCommand cmmandUnit = new PrintInboundPackageLabelCommand();
            cmmandUnit.setOrderNo(command.getOrderNo());
            cmmandUnit.setPrintSize(command.getPrintSize());
            cmmandUnit.setOrderNo(command.getOrderNo());
            if (i == count - 1) {
                cmmandUnit.setPackageSernoList(command.getPackageSernoList().subList(i * unit, total));
            } else {
                cmmandUnit.setPackageSernoList(command.getPackageSernoList().subList(i * unit, (i + 1) * unit));
            }
            taskList.add(exec.submit(new CallableTask(inboundPackageService, cmmandUnit)));

        }

        for (Future<List<String>> future : taskList) {
            try {
                List<String> list = future.get();
                result.addAll(list);

            } catch (Exception e) {
                logger.error("批量打印包裹条码失败", e);
                return null;
            } finally {
                exec.shutdown();
            }
        }
        return result;
    }

    class CallableTask implements Callable<List<String>> {

        private InboundPackageService           service;
        private PrintInboundPackageLabelCommand command;

        public CallableTask(InboundPackageService service, PrintInboundPackageLabelCommand command){
            super();
            this.service = service;
            this.command = command;
        }

        @Override
        public List<String> call() throws Exception {

            return service.printPackageLabel(command);
        }
    }

    /**
     * 创建海外仓入库单 保存到未提货/已提货状态
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/order/create")
    public String create(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object obj = requestMsg.getData();
        CreateInboundOrderCommand command = new CreateInboundOrderCommand();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, InputInboundCreate.winitProductCode.getName());
            //取Winit产品信息
            String winitProductCode = json.getString(InputInboundCreate.winitProductCode.getName());
            WinitProductQueryCommand winitProductQueryCommand = new WinitProductQueryCommand();
            winitProductQueryCommand.setCode(winitProductCode);
            winitProductQueryCommand.setCtx(CommandContext.getContext());
            WinitProduct  winitProduct =  winitProductService.queryProduct(winitProductQueryCommand);
            if(null == winitProduct){
            	 throw new ApiException(ErrorCode.WINIT_PRODUCT_NOT_EXISTS, winitProductCode);
            }
            winitProduct.setIsContainTransnationalTransportSu(this.isContainLogisticsSu(winitProductCode)?"Y":"N");
            
            
            InboundOrderfieldValidator.validInboundOrder(json,winitProduct);
            InboundOrderVo vo = InboundOrderBuilder.build(json,winitProduct);
            vo.setOrderSource("API");//订单来源
            if("Y".equals(winitProduct.getIsSelfInspection())){
            	vo.setIsSelfInspection("Y");
            	vo.setInspectionType(InboundEnumConstant.InspectionTypeStatus.SELF_INSPECTION.getVal());
            }
            vo.setCustomerId(Long.valueOf(CommandContext.getContext().getUserId()));
            command.setInboundOrder(vo);
        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }

        // 调用接口创建入库单
        String orderNo = inboundOrderService.createInboundOrder(command);
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("orderNo", orderNo);
        responseMsg.setData(resultMap);
        responseMsg.setMsg("SUCCESS");
        return SUCCESS;
    }
    
    
    /**
     * 上传报关资料
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/order/uploadCustomsDeclareDocs")
    public String uploadCustomsDeclarationDocuments(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object obj = requestMsg.getData();
        BatchAddInboundCustomsDataFileCommand command = new BatchAddInboundCustomsDataFileCommand();
        if (obj instanceof JSONObject) {
            JSONObject json = (JSONObject) obj;
            ValidateUtil.validNotNull(json, "orderNo");
            ValidateUtil.validNotNull(json, "docType");
            ValidateUtil.validMaxLength(json, "orderNo", "orderNo",50,true);
            ValidateUtil.validMaxLength(json, "docType", "docType",50,true);
            ValidateUtil.validNotNull(json, "customsDeclarationDocs");
            ValidateUtil.validList(json, "customsDeclarationDocs", true);
            String winitOrderNo = json.getString("orderNo");
            String docType = json.getString("docType");
            if(!"EXPORT".equals(docType) && !"IMPORT".equals(docType)){
            	 throw new ApiException(ErrorCode.FIELD_TYPE_ERROR,"docType");
            }
            JSONArray customsDeclarationDocsArray = json.getJSONArray("customsDeclarationDocs");
            if (customsDeclarationDocsArray.size() == 0) {
                throw new ApiException(ErrorCode.FIELD_NOT_NULL);
            }
            if (customsDeclarationDocsArray.size() > 10) {
                throw new ApiException(ErrorCode.CUSTOMS_FILE_QUANTITY_EXCEED_LIMIT,10);
            }
            List<InboundCustomsDataFileVo> fileList = new ArrayList<InboundCustomsDataFileVo>();
            int maxfileLength = 5*1024*1024;
            Float maxBase64Float = maxfileLength * 1.35f; 
            int maxBase64Length = maxBase64Float.intValue();
            for (Object docJsonObj : customsDeclarationDocsArray) {
                JSONObject docJson = (JSONObject) docJsonObj;
                ValidateUtil.validNotNull(docJson, "fileName", "fileName");
                ValidateUtil.validNotNull(docJson, "fileType", "fileType");
                ValidateUtil.validNotNull(docJson, "fileData", "fileData");
                ValidateUtil.validMaxLength(docJson, "fileName", "fileName",50,true);
                ValidateUtil.validMaxLength(docJson, "fileType", "fileType",50,true);
                if(!isSupportFileType(docJson.getString("fileType"))){
                	 throw new ApiException(ErrorCode.CUSTOMS_FILE_TYPE_NOT_SUPPORT,docJson.getString("fileType"));
                }
                
                String fileDataBase64 = docJson.getString("fileData");
                if(fileDataBase64.length() > maxBase64Length  ){
                	throw new ApiException(ErrorCode.CUSTOMS_FILE_SIZE_MUST_LESS_THAN_XM,5);
                }
                byte[] fileDataBytes =  Base64.base64ToByteArray(fileDataBase64);
                if(fileDataBytes.length  > maxfileLength){
                	throw new ApiException(ErrorCode.CUSTOMS_FILE_SIZE_MUST_LESS_THAN_XM,5);
                }
                
                String fullFileName = null;
                String fileName = docJson.getString("fileName").trim();
                String suffix   = docJson.getString("fileType").trim();
                
                if(fileName.endsWith("."+suffix)
                	|| fileName.endsWith("."+suffix.toUpperCase())
                	|| fileName.endsWith("."+suffix.toLowerCase())){
                	fullFileName = fileName;
                }else{
                	fullFileName = fileName + "." + suffix;
                }
                
                InboundCustomsDataFileVo vo = new InboundCustomsDataFileVo();
                vo.setCustomsDataType("EXPORT".equals(docType) ? "export":"import");
                vo.setFileDataBytes(fileDataBytes);
                vo.setFileName(fullFileName);
                vo.setWinitOrderNo(winitOrderNo);
                fileList.add(vo);
            }
            command.setCustomsDataFileList(fileList);
        } else {
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }
        command.setCtx(CommandContext.getContext());
        List<InboundCustomsDataFileVo> resultList = inboundCustomsDataFileService.batchAddInboundCustomsDataFiles(command);
        List<Map<String,Object>> customsDeclarationDocs = new ArrayList<Map<String,Object>>();
        for (InboundCustomsDataFileVo inboundCustomsDataFileVo : resultList) {
        	String fileName = inboundCustomsDataFileVo.getFileName();
        	Map<String, Object> file = new HashMap<String, Object>();
        	file.put("fileName", fileName.substring(0, fileName.lastIndexOf('.')));
        	file.put("fileType", fileName.substring(fileName.lastIndexOf('.'),fileName.length()));
        	customsDeclarationDocs.add(file);
        }
        
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("customsDeclarationDocs", customsDeclarationDocs);
        responseMsg.setData(resultMap);
        responseMsg.setMsg("SUCCESS");
        return SUCCESS;
    }
    
    private boolean isSupportFileType(String fileType){
    	for (String supportType : SUPPORT_FILE_TYPE) {
			if(supportType.equalsIgnoreCase(fileType)){
				return true;
			}
		}
    	return false;
    }

    /**
     * 判断产品是否包含跨国运输服务（空运、海运）
     * @param productCode
     * @return
     */
	private boolean isContainLogisticsSu(String winitProductCode) {
		 WinitProductQueryCommand suCommand = new WinitProductQueryCommand();
        suCommand.setCode(winitProductCode);
        String transportCategory = null;
        try {
            List<WinitProduct> serviceList = winitProductItemService.queryServiceItemAllByProductIdOrCode(suCommand);
            // 找出服务里的运输方式 空运:C0301|C030102 海运:C0302|C030202 快递:C0303
            if (Collections3.isNotEmpty(serviceList)) {
                for (WinitProduct serviceUnit : serviceList) {
                    if (EnumConstant.ThirdLevelCategory.CATEGORY_TRANSPORT_AIR.getCode()
                        .equals(serviceUnit.getServiceCatalogCode())
                        || EnumConstant.ThirdLevelCategory.CATEGORY_TRANSPORT_AIR_V2.getCode()
                            .equals(serviceUnit.getServiceCatalogCode())) {
                    	transportCategory = TMSConstants.KONGYUN_TYPE;
                        break;
                    } else if (EnumConstant.ThirdLevelCategory.CATEGORY_TRANSPORT_SEA.getCode()
                        .equals(serviceUnit.getServiceCatalogCode())
                               || EnumConstant.ThirdLevelCategory.CATEGORY_TRANSPORT_SEA_V2.getCode()
                                   .equals(serviceUnit.getServiceCatalogCode())) {
                    	transportCategory = TMSConstants.HAIYUN_TYPE;
                        break;
                    } else if (EnumConstant.ThirdLevelCategory.CATEGORY_TRANSPORT_EXPRESS.getCode()
                        .equals(serviceUnit.getServiceCatalogCode())) {
                    	transportCategory = TMSConstants.KUAIDI_TYPE;
                        break;
                    }
                }
            }
        } catch (Exception e) {
            logger.error("查询服务分类失败", e);
            throw new ApiException(ErrorCode.SYSTEM_ERROR);
        }
        return TMSConstants.KONGYUN_TYPE.equals(transportCategory) || TMSConstants.HAIYUN_TYPE.equals(transportCategory);
	        
	}
}
